#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "../../public/_public.h"

CLogFile logfile;
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("\n");
        printf("Using:./checkproc logfilename\n");

        printf("Example:/project/tools1/bin/procctl 10 /project/tools1/bin/checkproc /tmp/log/checkproc.log\n\n");

        printf("本程序用于检查后台服务程序是否超时，如果已超时，就终止它。\n");
        printf("注意：\n");
        printf("  1）本程序由procctl启动，运行周期建议为10秒。\n");
        printf("  2）为了避免被普通用户误杀，本程序应该用root用户启动。\n");
        printf("  3）如果要停止本程序，只能用killall -9 终止。\n\n\n");
        return -1;
    }

    if (logfile.Open(argv[1],"a+") == false)
    {
        printf("打开日志失败\n");
        return -1;
    }

    st_procinfo *shmptr = nullptr;
    int shm_id = 0;

    if (-1 == (shm_id = shmget(SHMKEYP, MAXNUMP * sizeof(st_procinfo), 0666 | IPC_CREAT)))
    {
        printf("创建共享内存失败\n");
        logfile.Write("创建共享内存失败\n");
        return -1;
    }
    // 连接贡献内存 shmat
    shmptr = (st_procinfo *)shmat(shm_id, 0, 0);

    // 遍历我们ipcs
    for (int i = 0; i < MAXNUMP; i++)
    {
        if (shmptr[i].pid == 0)
        {
            continue;
        }
        // extern int kill (__pid_t __pid, int __sig) __THROW;
        int sig = kill(shmptr[i].pid, 0);
        if (sig == -1)
        {
            logfile.Write("进程%d已经死亡\n",shmptr[i].pid);
            memset(shmptr + i, 0, sizeof(st_procinfo));
        }
        else
        {
            time_t now = time(0);
            if (now - shmptr[i].atime > shmptr[i].timeout)
            {

                kill(shmptr[i].pid, 15);
                int itr;
                for (int i = 0; i < 5; i++)
                {
                    sleep(1);
                    itr = kill(shmptr[i].pid, 0);
                    if (itr==-1) break;     // 进程已退出。
                }

                if (itr == -1)
                {
                    logfile.Write("进程%d已经死亡\n",shmptr[i].pid);
                    //* Set N bytes of S to C.  */
                    // extern void *memset (void *__s, int __c, size_t __n) __THROW __nonnull ((1));
                    memset(shmptr + i, 0, sizeof(st_procinfo));
                }
                else
                {
                    kill(shmptr[i].pid, 9);
                    logfile.Write("进程%d被强行杀死\n",shmptr[i].pid);
                    //* Set N bytes of S to C.  */
                    // extern void *memset (void *__s, int __c, size_t __n) __THROW __nonnull ((1));
                    memset(shmptr + i, 0, sizeof(st_procinfo));
                }
            }
            else
            {
                continue;
            }
        }
    }
}